package a12_19reflection;

import a0.reflection.Dog;
import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class RefectionDemo {


    /**
     * 获取类信息，字节码，三种方式
     * Class类：是所有类的类类型
     */
    @Test
    public void getClass_my()throws Exception{

        Dog dog = new Dog("wangwang","black",2);
        //1.
        Class dogClass =  dog.getClass();

        //2.
        Class dogClass2 = Dog.class;

        //3.
        Class dogClass3 = Class.forName("a0.reflection.Dog");

    }

    /**
     * 通过反射实例化对象
     */
    @Test
    public void instance(){
        Class<Dog> dogClass = Dog.class;

        try {
            //调用的默认的构造方法（没有默认的构造方法会报错）
            Dog dog = (Dog)dogClass.newInstance();
            System.out.println(dog.toString());

        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }

    /**
     *  获取所有的构造方法
     *
     */
    @Test
    public void test1()throws Exception{
        Class<Dog> dogClass = Dog.class;

        //获取所有的构造器
        Constructor[] constructors = dogClass.getConstructors();

        for (Constructor constructor : constructors) {
            System.out.println(constructor.getName());
            System.out.println(constructor.getParameterCount());
        }

        // 获取一个指定的构造方法
        Constructor constructor
                = dogClass.getConstructor(String.class, String.class, Integer.class);
        //调用带参数的构造器实例化对象
        Dog dog = (Dog) constructor.newInstance("xiaogou","wthite",3);

        System.out.println(dog.toString());

    }

    //获取所有的属性
    @Test
    public void test2(){
        Class<Dog> dogClass = Dog.class;

        //获取公有属性
        Field[] fields = dogClass.getFields();
        for (Field field : fields) {
            //属性名称
            System.out.println(field.getName());
            //属性修饰符
            System.out.println(field.getModifiers());
            //l类型
            System.out.println(field.getType());
        }

        //获取所有属性
        Field[] declaredFields = dogClass.getDeclaredFields();
        //System.out.println(declaredFields.length);

        for (Field declaredField : declaredFields) {
            //获取访问修饰符
            int modifiers = declaredField.getModifiers();
            System.out.println(modifiers);
            //获取修饰符（String类型）
            System.out.println(Modifier.toString(modifiers));
            System.out.println(declaredField.getName());
            System.out.println(declaredField.getType());
        }

    }

    //获取方法信息
    @Test
    public void test3() throws Exception{
        Class<Dog> dogClass = Dog.class;
        Dog dog = dogClass.newInstance();
        //获取包名
        Package aPackage = dogClass.getPackage();
        System.out.println(aPackage.getName());
        //获取公有方法，包括继承的公有方法
        Method[] methods = dogClass.getMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
            if (method.getName().equals("eat")){
                //让方法执行（传入对象参数）
                method.invoke(dog);
            }
        }
        //获取该对象所有方法(不包括父类方法)
        Method[] declaredMethods = dogClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod.getName());
            if (declaredMethod.getName().equals("eat1")){
                //设置私有方法可以被访问（去除访问修饰符检查）
                //如果不设置，调用私有方法会抛异常
                declaredMethod.setAccessible(true);
                declaredMethod.invoke(dog);
            }
        }
    }





}
